package com.yang.singleton;

import java.util.Objects;

/*
* 懒汉式+锁+双重检查
* 线程安全
* */
public class Singleton6 {

    //构造方法私有化
    private Singleton6(){}

    /*
    * 实例化一个对象要分为三个步骤：1分配内存空间、2初始化对象、3将内存空间的地址赋值给对应的引用
    * 但是由于重排序的缘故，步骤2、3可能会发生重排序，其过程如下：1分配内存空间、2将内存空间的地址赋值给对应的引用、3初始化对象
    * 如果2、3发生了重排序就会导致第二个判断会出错，singleton != null，但是它其实仅仅只是一个地址而已，此时对象还没有被初始化，所以return的singleton对象是一个没有被初始化的对象。
    * 所以加上volatile关键字禁止指令重排
     * */
    private volatile  static Singleton6 INSTANCE;

    public static Singleton6 getInstance() {
        if (Objects.isNull(INSTANCE)) {
            //双重检查
            synchronized (Singleton6.class) {
                if (Objects.isNull(INSTANCE)) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE = new Singleton6();
                }
            }
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 50; i++) {
            new Thread(() -> {
                System.out.println(Singleton6.getInstance().hashCode());
            }).start();
        }
    }
}
